package com.xd.core.system.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.XML;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xd.common.constant.SysConstant;
import com.xd.common.exception.XkdException;
import com.xd.common.util.*;
import com.xd.core.business.entity.Credit;
import com.xd.core.business.entity.IncomingInfo;
import com.xd.core.business.entity.RepaymentSchedule;
import com.xd.core.business.mapper.CreditMapper;
import com.xd.core.business.mapper.IncomingInfoMapper;
import com.xd.core.business.mapper.RepaymentScheduleMapper;
import com.xd.core.debt.entity.Debt;
import com.xd.core.debt.mapper.DebtMapper;
import com.xd.core.product.entity.Product;
import com.xd.core.product.mapper.ProductMapper;
import com.xd.core.system.dto.SendPhone;
import com.xd.core.system.entity.SysUser;
import com.xd.core.system.mapper.SysUserMapper;
import com.xd.core.system.service.MsmService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Api(tags = "短信验证")
@RestController
@RequestMapping("/msm")
@Slf4j
public class MsmController {

    @Autowired
    private MsmService msmService;
    @Value("${aes.key}")
    private String aesKey;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IncomingInfoMapper incomingInfoMapper;
    @Autowired
    private DebtMapper debtMapper;
    @Autowired
    private RepaymentScheduleMapper repaymentScheduleMapper;
    @Autowired
    private CreditMapper creditMapper;
    @Autowired
    private ProductMapper productMapper;
    @Value("${spring.profiles.active}")
    private String active;
    /*
    已逾期
     */
    public static final int STATUS_OVERDUE = 3;

    public static final String CONTENT = "【宝坤网络小额贷】尊敬的{}先生/女士，温馨提醒:您的贷款将于{}日还款，应还金额{}元。请确保您尾号{}的{}账户余额充足或及时主动还款。主动还款:请联系客户经理。";

    public static final String DELAY_CONTENT = "【宝坤网络小额贷】尊敬的{}先生/女士，您好!您在我司的借款已逾期{}天，当前应还金额:{}元，请尽快还款，若已还款，请忽略，如有疑问，请联系客户经理。感谢配合!";

    //发送短信的方法
    @ApiOperation("发送登陆验证码")
    @PostMapping("send")
    public void sendMsm(@RequestBody SendPhone phone) throws IllegalAccessException {
        //60秒内只准调用一次
        Object o = redisTemplate.opsForValue().get("past_code:" + phone.getPhone());
        if (o != null)
            throw new XkdException("发送验证码过于频繁，稍后再试");
        //2 如果redis获取 不到，进行阿里云发送
        //生成随机值，传递阿里云进行发送
        if (!XkdUtil.checkSign(phone, phone.getSign()))
            throw new XkdException("签名验证失败");
        String code = RandomUtil.getSixBitRandom();
        //调用service发送短信的方法
        String content = "【泛美星云】您的验证码{}，该验证码5分钟内有效，请勿将验证码泄漏于他人！";
        String isSend = msmService.sendSmsDJKJ(AESUtil.decrypt(phone.getPhone(), aesKey), StrUtil.format(content, code));
        if (isSend.equalsIgnoreCase("success")) {
            //发送成功，把发送成功验证码放到redis里面
            //设置有效时间
            redisTemplate.opsForValue().set("loginCode:" + phone.getPhone(), code, 60 * 5, TimeUnit.SECONDS);
            //60秒内只准调用一次
            redisTemplate.opsForValue().set("past_code:" + phone.getPhone(), "1", 60, TimeUnit.SECONDS);
            log.info("短信发送成功,验证码为：" + code);
        } else {
            log.info("短信发送失败");
            throw new XkdException("发送短信失败");
        }

    }

    //    @ApiOperation("发送忘记密码验证码")
//    @PostMapping("sendMsmPW")
//    public void sendMsmPW(@RequestBody SendPhone phone) throws IllegalAccessException {
//        //60秒内只准调用一次
//        Object o = redisTemplate.opsForValue().get("past_code:"+phone.getPhone());
//        if (o!=null)
//            throw new XkdException("发送验证码过于频繁，稍后再试");
//        //2 如果redis获取 不到，进行阿里云发送
//        //生成随机值，传递阿里云进行发送
//        if (!XkdUtil.checkSign(phone,phone.getSign()))
//            throw new XkdException("签名验证失败");
//        String code = RandomUtil.getSixBitRandom();
//        //调用service发送短信的方法
//        String content = "【泛美星云】您正在执行修改密码操作，验证码为{}，工作人员不会向你索要验证码，请勿向他人泄露验证码！";
//        String isSend = msmService.sendSmsDJKJ(AESUtil.decrypt(phone.getPhone(), aesKey), StrUtil.format(content,code));
//        if(isSend.equalsIgnoreCase("success")) {
//            //发送成功，把发送成功验证码放到redis里面
//            //设置有效时间
//            redisTemplate.opsForValue().set("updatepw:"+phone.getPhone(),code,60*2, TimeUnit.SECONDS);
//            //60秒内只准调用一次
//            redisTemplate.opsForValue().set("past_code:"+phone.getPhone(),"1",60, TimeUnit.SECONDS);
//            log.info("短信发送成功,验证码为："+code);
//        } else {
//            log.info("短信发送失败");
//            throw new XkdException("发送短信失败");
//        }
//
//    }
    @ApiOperation("放款验证码")
    @GetMapping("sendOutAmount")
    public String sendOutAmount(Integer companyId) {
        if (!active.equals("prd")) {
            return null;
        }
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getCompanyId, companyId).eq(SysUser::getUserType, SysConstant.USER_TYPE_P));
        String phone = sysUser.getPhone();
        String timestamp = OrderNumUtil.sendOutCode();
        //10秒内只准调用一次
        Object o = redisTemplate.opsForValue().get("out_past_code:" + ":" + phone);
        if (o != null)
            throw new XkdException("发送验证码过于频繁，10秒稍后再试");
        String code = RandomUtil.getSixBitRandom();
        //调用service发送短信的方法
        String content = "【泛美星云】您的验证码{}，该验证码5分钟内有效，请勿将验证码泄漏于他人！";
        String isSend = msmService.sendSmsDJKJ(AESUtil.decrypt(phone, aesKey), StrUtil.format(content, code));
        if (isSend.equalsIgnoreCase("success")) {
            //发送成功，把发送成功验证码放到redis里面
            //设置有效时间
            redisTemplate.opsForValue().set("out_amount:" + timestamp + phone, code, 60 * 5, TimeUnit.SECONDS);
            //60秒内只准调用一次
            redisTemplate.opsForValue().set("out_past_code:" + phone, "1", 10, TimeUnit.SECONDS);
            log.info("短信发送成功,验证码为：" + code);
        } else {
            log.info("短信发送失败");
            throw new XkdException("发送短信失败");
        }
        return timestamp;
    }
    @PreAuthorize("hasAnyAuthority('sys:AccountsReceivableList-SmsNotification')")
    @ApiOperation("短线提醒")
    @GetMapping("sendOfflineRepay")
    public void sendOfflineRepay(Integer incomingId,Integer outId) {
        // 从Redis获取当天发送短信次数，默认为0
        Integer counts = Optional.ofNullable((Integer) redisTemplate.opsForValue().get("sendMessage" + outId)).orElse(0);
        if (counts > 1) {
            throw new XkdException("短信提醒一天只能发送两次");
        }

        // 获取相关业务数据
        IncomingInfo incomingInfo = incomingInfoMapper.selectById(incomingId);
        Credit credit = creditMapper.selectOne(new LambdaQueryWrapper<Credit>().eq(Credit::getIncomingId, incomingId));
        Debt debt = debtMapper.selectOne(new LambdaQueryWrapper<Debt>().eq(Debt::getOutId, outId));

        // 校验债权是否允许代扣
        if (debt.getIsWithhold().equals("1")) {
            throw new XkdException("该笔债权不进行代扣，无法确定用户还款方式。无法发送提示短信！");
        }

        // 准备短信内容
        String phone;
        String name ;
       Integer productId=  incomingInfo.getProductId();
       Product product= productMapper.selectById(productId);
       if(product.getType().equals(SysConstant.PRODUCT_FIVE) && incomingInfo.getPrincipalType().equals("1")){
           phone = incomingInfo.getLegalPhone();
           name = incomingInfo.getLegalEntityName();

       }else{
           phone =  incomingInfo.getPhone();
           name = incomingInfo.getName();

       }
        String sendPhone  = AESUtil.decrypt(phone, aesKey);
        String lastFourDigits = credit.getRepayAccount().substring(credit.getRepayAccount().length() - 4);
        String bank = credit.getRepayBank();


        // 构建短信内容
        String content;
        if ("1".equals(debt.getIsEarly())) {
            content = buildEarlyRepaymentMessage(debt, name, lastFourDigits, bank);
        } else {
            content = buildNormalRepaymentMessage(debt, name, lastFourDigits, bank, repaymentScheduleMapper);
        }

        // 发送短信并更新计数
        String result = msmService.sendH5(sendPhone, content, content);
        if ("success".equals(result)) {
            log.info("短信发送成功");
            long expirationSeconds = XkdUtil.getNowToNextDaySeconds();
            redisTemplate.opsForValue().set("sendMessage" + outId, counts + 1, expirationSeconds, TimeUnit.SECONDS);
        }
    }

        // 构建提前还款短信内容的方法
        private String buildEarlyRepaymentMessage(Debt debt, String name, String lastFourDigits, String bank) {
            BigDecimal amount = debt.getEarlyAmount();
            if (debt.getStatus() == STATUS_OVERDUE) {
                return StrUtil.format(DELAY_CONTENT, name, debt.getOverdueDays(), amount);
            } else {
                String repaymentDate = DateUtil.format(debt.getEarlyDate(), "yyyy-MM-dd");
                return StrUtil.format(CONTENT, name, repaymentDate, amount, lastFourDigits, bank);
            }
        }

        // 构建正常还款短信内容的方法
        private String buildNormalRepaymentMessage(Debt debt, String name, String lastFourDigits, String bank, RepaymentScheduleMapper repaymentScheduleMapper) {
            // 查询未还和逾期的账单
            LambdaQueryWrapper<RepaymentSchedule> wrapper = new LambdaQueryWrapper<RepaymentSchedule>()
                    .eq(RepaymentSchedule::getOutId, debt.getOutId())
                    .in(RepaymentSchedule::getStatus, "0", "2")
                    .orderByAsc(RepaymentSchedule::getId);

            List<RepaymentSchedule> repaymentSchedules = repaymentScheduleMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(repaymentSchedules)) {
                throw new XkdException("没有查询到未还和逾期的账单");
            }

            RepaymentSchedule repaymentSchedule = repaymentSchedules.get(0);
            BigDecimal totalAmount = repaymentSchedule.getAmount()
                    .add(debt.getDefaultInterestTodo())
                    .add(debt.getOverdueInterest());

            if (debt.getStatus() == STATUS_OVERDUE) {
                return StrUtil.format(DELAY_CONTENT, name, debt.getOverdueDays(), totalAmount);
            } else {
                String repaymentDate = DateUtil.format(repaymentSchedule.getRepaymentDate(), "yyyy-MM-dd");
                return StrUtil.format(CONTENT, name, repaymentDate, totalAmount, lastFourDigits, bank);
            }
    }









    public static void main(String[] args) {


        RestTemplate restTemplate = new RestTemplate();

        String url = "http://120.79.8.118:8088/sendSMS.action";
        HashMap<String, Object> map = new HashMap<>();
        map.put("enterpriseID", "9127201");
        map.put("loginName", "admin");
        String s = MD5Util.MD5a32("kahsb51478");
        map.put("password", s);
        String content = "【有鑫贷】 验证码122046，这才是常规内容";
        map.put("content", content);
        map.put("mobiles", "15228887219");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 表单格式
        // 构造表单参数体
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.setAll(map); // 把 Map<String, String> 转成 MultiValueMap
        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(body, headers);
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, request, String.class);
        String body1 = stringResponseEntity.getBody();
        JSONObject jsonObject = XML.toJSONObject(body1);
        System.out.println(jsonObject);
    }


}
